/*
 * Copyright (C), 2015-2018
 * FileName: Solution046
 * Author:   zhao
 * Date:     2018/12/4 19:35
 * Description: 46. 全排列
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.lizhaoblog.mid;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 〈一句话功能简述〉<br>
 * 〈46. 全排列〉
 *
 * @author zhao
 * @date 2018/12/4 19:35
 * @since 1.0.1
 */
public class Solution046 {
    /**************************************
     * 题目
     给定一个没有重复数字的序列，返回其所有可能的全排列。

     示例:

     输入: [1,2,3]
     输出:
     [
     [1,2,3],
     [1,3,2],
     [2,1,3],
     [2,3,1],
     [3,1,2],
     [3,2,1]
     ]
     **************************************/

    /*************************************
     想法：
     将原数组，最终结果数组，某次的数组 进行递归
     当循环到最后一个的时候，就往最终结果数组 里面  添加 某次的数组
     如果没循环到最后一个的时候,继续调用原来的归方法
     我的做法

     超过26%的测试案例
     时间复杂度/空间复杂度：  /n

     代码执行过程：
     nums=[1,2,3],smallResult = [],result = []




     总结：
     ************************************/
    public List<List<Integer>> permute(int[] nums) {

        if (nums.length == 0) {
            return Collections.EMPTY_LIST;
        }

        List<List<Integer>> result = new ArrayList<>();
        List<Integer> smallResult = new ArrayList<>();
        repick(nums, result, smallResult);
        return result;
    }

    private void repick(int[] nums, List<List<Integer>> result, List<Integer> smallResult) {
        System.out.println("result: " + result.toString() + "smallResult: " + smallResult.toString());
        if (smallResult.size() == nums.length) {
            result.add(new ArrayList<Integer>(smallResult));
        } else {
            for (int i = 0; i < nums.length; i++) {
                if (smallResult.contains(nums[i])) {
                    continue;
                }
                smallResult.add(nums[i]);
                repick(nums, result, smallResult);
                smallResult.remove(smallResult.size() - 1);
            }

        }
    }

    /**************************************
     * 比我好的答案 better
     * ***********************************/
    public List<List<Integer>> better(int[] nums) {
        List<List<Integer>> result = new ArrayList<List<Integer>>();
        if (nums == null || nums.length == 0) {
            return result;
        }
        List<Integer> list = new ArrayList<Integer>();
        permute(nums, result, 0, list);
        return result;
    }

    public void permute(int[] nums, List<List<Integer>> result, int index, List<Integer> list) {
        if (index == nums.length) {
            List<Integer> array = new ArrayList<Integer>(list);
            result.add(array);
            return;
        }
        for (int i = index; i < nums.length; i++) {
            swap(nums, index, i);
            list.add(nums[index]);
            permute(nums, result, index + 1, list);
            // 当list里面存的是Integer的时候，删除Integer传递的int参数，是删除相应位置的元素还是删除对应的Integer对象
            list.remove(list.size() - 1);
            swap(nums, index, i);
        }
    }

    public void swap(int[] nums, int left, int right) {
        if (left == right) {
            return;
        }
        nums[left] ^= nums[right];
        nums[right] ^= nums[left];
        nums[left] ^= nums[right];
    }

}
